package com.zeroes.cons;

import android.app.Activity;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.hardware.SensorEvent;
import android.util.Log;
import org.mozilla.javascript.*;
import org.zeroes.Components.ZSSingle;
import org.zeroes.Events.*;

import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;

import org.zeroes.common_prelude.CGSize;
import org.zeroes.common_prelude.vector2;
import org.zeroes.common_prelude.Vertex3;
import org.zeroes.svg.*;


public class ZSGameManager {

	
	private static ZSGameManager _manager = new ZSGameManager();
	private ZSGame currentGame;
	public CGSize screenSize;
	private boolean stoped=false;
	public vector2 lt=new vector2(-1,-1);
	private Vertex3 la = new Vertex3(0,0,0);
	public ZSSprite fS;
	// static constants
	public static final int GAME_TYPE_SVG_WITH_JAVASCRIPT=0; 
	public static final int GAME_TYPE_ALL_PURE_JAVA=1; 
	private ProgressDialog pdialog=null;
	private Dialog dialog=null;
	   public static ZSGameManager AskMe() {
//	        if (_sharedDirector != null)
	            return _manager;
	   }
	   
	   
	   public ZSGameManager(){
		   currentGame=new ZSGame();
	   }
	   
	   public Context ctx = null;
	   public ZSRenderer GL;
	   public ZSEventSheet events;
	   public void setContext(Context c){
		   
		   ctx=c;
	   }
	   public int[] winSize(){
		   int[] r = new int[2];
		   r[0]=GL.mWidth;
		   r[1]=GL.mHeight;
		   return r;
	   }
	   public ZSGameManager useRenderer (ZSRenderer r){
		   
		   GL=r;
		   ctx=r.mContext;
		   return _manager;
		   
	   }
	   public ZSGame forCurrentGame(){
		   
		   return this.currentGame;
	   }
	   public void toRun(ZSGame agame){
		   this.currentGame=agame;
		   events= new ZSEventSheet(agame);
		   this.loadSysCbs();
		   currentGame.runEvents(events); 
		   String source="";
		   if(currentGame.gameOptions.gameType==this.GAME_TYPE_SVG_WITH_JAVASCRIPT){
			   source=this.loadscripts(currentGame.gameOptions.jsSourceFileName);
			   
		   }
		   org.mozilla.javascript.Context cx = org.mozilla.javascript.Context.enter();
		   cx.setOptimizationLevel(-1);
			
	        try {
	            // Initialize the standard objects (Object, Function, etc.)
	            // This must be done before scripts can be executed. Returns
	            // a scope object that we use in later calls.
	            Scriptable scope = cx.initStandardObjects();

	            Object wrappedEv = org.mozilla.javascript.Context.javaToJS(events, scope);
	            ScriptableObject.putProperty(scope, "events", wrappedEv );
	           
	            Object wrappedgame = org.mozilla.javascript.Context.javaToJS(currentGame, scope);
	            ScriptableObject.putProperty(scope, "game", wrappedgame );
	            
	            // Collect the arguments into a single string.
	            


	            // Now evaluate the string we've colected.
	            Object result = cx.evaluateString(scope, source, "onCreate:", 1, null);
         

	        } finally {
	            // Exit from the context.
	        	org.mozilla.javascript.Context.exit();
	        }
		   
	   }
	   
	   public int getupdaterateforcurrentGame(){
		   
		   return this.currentGame.updateRate;
	   }
	   
	 
	 //  public ZSSprite[] scene = new ZSSprite[10];
	 
	   private String loadscripts(String fn){
		   
		  
//	     InputStream inputStream = getResources().openRawResource(R.raw.internals);
	     
	     ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();

	     int i;
	  try {
		  InputStream inputStream = ctx.getAssets().open(fn);
	   i = inputStream.read();
	   while (i != -1)
	      {
	       byteArrayOutputStream.write(i);
	       i = inputStream.read();
	      }
	      inputStream.close();
	  } catch (IOException e) {
	   // TODO Auto-generated catch block
	   e.printStackTrace();
	  }

	     return byteArrayOutputStream.toString();
	   }
	   
	   
	  
	  public DomParser gameDOM(){
		  
		  return currentGame.domparser;
	  }
	  
	  public void updateGameLogic(float dt){
		  if(!stoped)
		  currentGame.update(dt);
		  
	  }
	  
	  public void tick(float alpha){
		  
		 /* ZSSprite obj = scene.get(0);
		  obj.visit();
		  
		  ZSSprite obj1 = scene.get(1);
		  obj1.visit();*/
		  if(!stoped)
		  currentGame.draw(alpha);
	  }
	  
	  public void notify(int notification){
		  if (notification==GL.SURFACE_CHANGED_SIZE) 
		  {
			/*  ZSSprite obj = scene.get(0);
			  obj.marktransformDirty();
			  
			  ZSSprite obj1 = scene.get(1);
			  obj1.marktransformDirty();*/
			  currentGame.markTransformDirty();
		  }
		  ConstructoidActivity a = (ConstructoidActivity)ctx;
		//  Log.v("gtrans", "getResumes : "+a.getResumes());
		  if (notification==GL.CAN_START_ASSET_LOADING) 
		  {

			  if(a.getResumes()==1)
			  currentGame.initialize();
			  else
				  assetReloading();
		  }
		  
	  }
	  public void dispatchAccelerometerData(SensorEvent event){
		  
			float[] values = event.values;
			// Movement
			/*float x = values[0];
			float y = values[1];
			float z = values[2];*/
			la.x=values[0];
			la.y=values[1];
			la.z=values[2];
			//Log.v("gtrans", "Acc x:"+x+" "+y+" "+z);
			
			currentGame.E.makeOnce("Sys.Accelerometer.changed", new Condback(){
				
				public void is(String evName, int idx){
					
					ZSPair<Vertex3,String> poz = new ZSPair<Vertex3,String> (la,null); 
					ZSEvent ev = new ZSEvent(evName,poz,0);
					currentGame.E._(evName, ev);
					
				}
			});


	  }
	  public void dispatchTouch(MotionEvent ev){
		  TouchCentral.AskMe().processEvent(ev);
		  
		  
		  int mod=TouchCentral.AskMe().lastTouch.mode;
		  float ltx=0,_lty=0;
			if(mod==TouchCentral.SINGLE_UP){
			 ltx = TouchCentral.AskMe().lastTouch.upX;
			_lty=TouchCentral.AskMe().lastTouch.upY;
			lt.x=(int)ltx;
			lt.y=(int)_lty;
		
			currentGame.E.makeOnce("Sys.touch.up", new Condback(){
				
				public void is(String evName, int idx){
					
					ZSPair<vector2,String> poz = new ZSPair<vector2,String> (lt,""); 
					ZSEvent ev = new ZSEvent(evName,poz,0);
					currentGame.E._(evName, ev);
					
				}
			});
			}
			
			if(mod==TouchCentral.SINGLE){
				 ltx = TouchCentral.AskMe().lastTouch.lastX;
				_lty=TouchCentral.AskMe().lastTouch.lastY;
				lt.x=(int)ltx;
				lt.y=(int)_lty;
			
				currentGame.E.makeOnce("Sys.touch.down", new Condback(){
					
					public void is(String evName, int idx){
						
						ZSPair<vector2,String> poz = new ZSPair<vector2,String> (lt,""); 
						ZSEvent ev = new ZSEvent(evName,poz,0);
						//ZSPair<ZSGame,String> g = new ZSPair<ZSGame,String> (currentGame,""); 
						//ev.complements.add(g);
						currentGame.E._(evName, ev);
						
					}
				});
				}
			
			if(mod==TouchCentral.DRAG){
				 ltx = TouchCentral.AskMe().lastTouch.dx;
				_lty=TouchCentral.AskMe().lastTouch.dy;
				lt.x=(int)ltx;
				lt.y=(int)_lty;
			
				currentGame.E.makeOnce("Sys.touch.drag", new Condback(){
					
					public void is(String evName, int idx){
						
						ZSPair<vector2,String> poz = new ZSPair<vector2,String> (lt,""); 
						ZSEvent ev = new ZSEvent(evName,poz,0);
						currentGame.E._(evName, ev);
						
					}
				});
				}
		//  ZSSprite obj = scene.get(0);
		currentGame.onTouch();
	  }
	   
	  
	  private void loadSysCbs(){
		  
			events.on("*.touch.*", new Callback(){
				public void run(String p, ZSEvent e){
					//System.err.println("touch up from java .... "+p);
					vector2 loc = e.castToVector2D(e.who);
					String[] items = p.split("\\.");
					if(!items[2].equals("drag")){
					ZSGame g = ZSGameManager.AskMe().currentGame;
					if(items[2].equals("up"))
					g.setCurrentSprite(null);
					for(ZSLayer l: g.Layers){
						for(ZSSprite s:l.Content){

							if(s.containPoint(loc)){
								fS=s;
								g.setCurrentSprite(s);
								events.makeOnce(s.tag+".touched."+items[2],new Condback(){
									
									public void is(String n, int idx){
										ZSEvent ev = new ZSEvent(n,null,0);
										ZSPair<ZSSprite,String> ss = new ZSPair<ZSSprite,String> (fS,""); 
										ev.complements.add(ss);
										events._(n, ev);
										
									}
								});
								
							}
							
						}
						
					}
					}
				}
			});
			
		  
		  
		  
	  }
	  
	  public void toStop(){
		  
		  stoped=true;
	  }
public void changeGameTo(ZSGame _game){
	currentGame.clearAll();
	
	Activity c = (Activity)ctx;
	c.runOnUiThread(new Runnable() {
	    public void run() {
	    	//Toast.makeText(ctx, "LOADING ... PLEASE WAIT!", Toast.LENGTH_LONG).show();
	       runProgressDialog();
	        
	    //	dialog.show();
	    }
	});
	
	_game.StartNewLevel();
	this.toRun(_game);
	
}

public void runProgressDialog(){
	pdialog=ProgressDialog.show(ctx, "", 
            "Loading. Please wait...", true);
}

public void dismissProgressDialog(){
	if(pdialog!=null&&pdialog.isShowing())
	pdialog.dismiss();
}

public void pauseCurrentGame(){
	GL.pause();
	currentGame.E._("sys.paused.thisgame");
	/*Activity c = (Activity)ctx;
	c.runOnUiThread(new Runnable() {
	    public void run() {
	    	//Toast.makeText(ctx, "LOADING ... PLEASE WAIT!", Toast.LENGTH_LONG).show();
	    	dialog = new Dialog(ctx);
	    	dialog.setContentView(R.layout.pausedialog);
	        dialog.setTitle("GAME PAUSED !");
	        dialog.setCancelable(true);
	        //there are a lot of settings, for dialog, check them all out!

	        //set up text
	       // TextView text = (TextView) dialog.findViewById(R.id.TextView01);
	       // text.setText("Text view");

	        //set up image view
	        ImageView img = (ImageView) dialog.findViewById(R.id.ImageView01);
	        img.setImageResource(R.raw.zssigla);

	        //set up button
	        Button button = (Button) dialog.findViewById(R.id.Button01);
	        button.setOnClickListener(new OnClickListener(){
	
	        	public void onClick(View v) {
	        		GL.resume();
	        		dialog.dismiss();
	        	}
	        });
	        //now that the dialog is set up, it's time to show it    
	        dialog.show();
	        
	    //	dialog.show();
	    }
	});*/
	
}

public void resumeCurrentGame(){
	Activity c = (Activity)ctx;
	c.runOnUiThread(new Runnable() {
	    public void run() {
	    	//Toast.makeText(ctx, "LOADING ... PLEASE WAIT!", Toast.LENGTH_LONG).show();
	    	dialog = new Dialog(ctx);
	    	dialog.setContentView(R.layout.pausedialog);
	        dialog.setTitle("GAME PAUSED !");
	        dialog.setCancelable(true);
	        //there are a lot of settings, for dialog, check them all out!

	        //set up text
	       // TextView text = (TextView) dialog.findViewById(R.id.TextView01);
	       // text.setText("Text view");

	        //set up image view
	        ImageView img = (ImageView) dialog.findViewById(R.id.ImageView01);
	        img.setImageResource(R.raw.zssigla);

	        //set up button
	        Button button = (Button) dialog.findViewById(R.id.Button01);
	        button.setOnClickListener(new OnClickListener(){
	
	        	public void onClick(View v) {
	        		currentGame.E._("sys.resumed.thisgame");
	        		GL.resume();
	        		
	        		dialog.dismiss();
	        	}
	        });
	        //now that the dialog is set up, it's time to show it    
	        dialog.show();
	        
	    //	dialog.show();
	    }
	});
	//GL.resume();
}

public void toEXIT(){
	Activity c = (Activity)ctx;
	c.finish();
}

private void assetReloading(){
	
	currentGame.assetReload();
}

public void setDesignScreenSize(int width,int height){
	
	currentGame.computeDARatio(width, height);
}

public void setScreenSize(int w,int h){
	
	this.screenSize=CGSize.make(w, h);
}
public void FrameRate(float fr){
	ZSPair<Integer,String> rate = new ZSPair<Integer,String> ((int)fr,"");
	ZSEvent ev = new ZSEvent("sys.computed.framerate",null,0);
	ev.complements.add(rate);
	currentGame.E._("sys.computed.framerate",ev);
}
}
